package org.gpp.proj1.communication.sender;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import junit.framework.TestCase;

import org.gpp.proj1.communication.CommunicationException;
import org.gpp.proj1.communication.ConnectionException;
import org.gpp.proj1.communication.processor.RMIRequestProcessor;
import org.gpp.proj1.communication.processor.test.RequestCounter;
import org.gpp.proj1.communication.protocol.Message;
import org.gpp.proj1.communication.protocol.ProtocolIdentifiers;
import org.gpp.proj1.communication.sender.manager.RequestSenderManagerIF;

public class RMIRequestSenderTest extends TestCase {
	
	private static final int TEST_PORT = 1099;
	
	/**
	 * @throws RemoteException
	 * @throws CommunicationException
	 * @throws ConnectionException
	 */
	public void testSendRequest() throws RemoteException, CommunicationException, ConnectionException {
		RequestSenderManagerIF managerMock = createMock( RequestSenderManagerIF.class );
		RequestSenderManagerIF managerMock2 = createMock( RequestSenderManagerIF.class );
		
		// Starting request processors
		RMIRequestProcessor processor = new RMIRequestProcessor( managerMock, TEST_PORT );
		processor.startup();
		
		// This proc must be online because the server will try to contact it
		RMIRequestProcessor processor2 = new RMIRequestProcessor( managerMock2, TEST_PORT + 1 );
		processor2.startup();		

		// Connecting to server
		RequestSenderIF sender = RMIRequestSender.connectToServer(managerMock2, TEST_PORT + 1, "localhost", TEST_PORT);
		
		// Creating and registeringfake request listener
		RequestCounter requestCounter = new RequestCounter();
		processor.registerListener( requestCounter  );
		
		// Recording mock - it must confirm the client id
		reset( managerMock );		
		managerMock.contains( eq( sender.getClientId() ) ); expectLastCall().andReturn( true );
		replay( managerMock );
		
		// Sending fake message		
		Message preparedMessage = new Message( ProtocolIdentifiers.CHAT, new String[]{} );
		sender.send( preparedMessage );
		
		// Verifying mocks
		verify( managerMock );
		
		// Checking if listener was notified
		assertEquals( 1, requestCounter.received.size() ) ;
		assertEquals( ProtocolIdentifiers.CHAT, requestCounter.received.get(0).getIdentifier() );
		assertEquals( sender.getClientId(), requestCounter.received.get(0).getSenderId() );
		
		// Unbinding processors
		try {
			LocateRegistry.getRegistry( TEST_PORT ).unbind( RMIRequestProcessor.REQUEST_PROCESSOR );
			LocateRegistry.getRegistry( TEST_PORT + 1 ).unbind( RMIRequestProcessor.REQUEST_PROCESSOR );
		} catch (NotBoundException e) {
			fail();
		}
	}
}
